package com.example.security.provider.impl;

import com.example.security.exception.MobileCodeNotFoundException;
import com.example.security.properties.CompanyProperties;
import com.example.security.provider.MobileRedisProvider;
import com.example.security.utils.ShiroPublicUtil;
import com.example.security.utils.jwt.CheckResult;
import com.example.security.utils.jwt.JwtUtils;
import com.example.security.utils.jwt.SystemConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class MobileRedisProviderImpl implements MobileRedisProvider {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private CompanyProperties companyProperties;

    @Override
    public void save(String mobile) {
        String code = UUID.randomUUID().toString().substring(0, 4);
        String key = companyProperties.getMobileCode().getName().concat(":").concat(mobile);
        //设置手机号和验证码绑定,并让验证码jwt,可以看作进行过期时间jwt的验证
        String jwtCode = JwtUtils.createJWT(code, code, companyProperties.getMobileCode().getTime() * 60 * 1000);
        redisTemplate.opsForValue().set(key, jwtCode, companyProperties.getMobileCode().getTime(), TimeUnit.MINUTES);
        log.warn("给手机号[ {} ]发生一条短信 验证码为: [ {} ]", mobile, code);
    }

    @Override
    public void validate(String mobile, String code) {
        //redis中存储的手机号key
        String key = companyProperties.getMobileCode().getName().concat(":").concat(mobile);
        //redis中取的已经有的jwtCode,需要后续解析
        String redisCodeJwt = redisTemplate.opsForValue().get(key);
        if (ShiroPublicUtil.isEmpty(redisCodeJwt)) {
            log.error("手机号验证码登入校验失败 改手机号没有验证码 mobile=[ {} ]", mobile);
            throw new MobileCodeNotFoundException("改手机号没有验证码 !!!");
        }
        CheckResult checkResult = JwtUtils.validateJWT(redisCodeJwt);
        if (checkResult.isSuccess()) {
            String redisCode = checkResult.getClaims().getId();
            //校验redis中存储的验证码是否和前端传回来的验证码相同
            if (!redisCode.equals(code)) {
                log.error("手机号验证码登入校验失败 mobile=[ {} ],code=[ {} ],实际redis验证码为:[ {} ]", mobile, code, redisCode);
                throw new MobileCodeNotFoundException("手机号验证码验证错误!!!");
            }
        } else {
            switch (checkResult.getErrCode()) {
                // 签名验证不通过
                case SystemConstant.JWT_ERRCODE_FAIL:
                    log.error("手机号验证码登入jwt校验失败 签名验证不通过");
                    break;
                //超时
                case SystemConstant.JWT_ERRCODE_EXPIRE:
                    log.error("手机号验证码登入jwt校验失败 签名验证过期");
                    break;
                default:
                    break;
            }
            throw new MobileCodeNotFoundException("手机号验证码验证错误!!!");
        }
    }
}
